
// system.cpp : windows main loops and stuff.
//
#include "Koswin.h"
#include "Resource.h"
#include "mmsystem.h"

#define MAX_LOADSTRING 100

// Global Variables:

bool m_Active=false;
bool m_Quitting=false;
HDC hDC;				/* device context */
HPALETTE hPalette = 0;			/* custom palette (if needed) */
HWND  hWnd;				/* window */

//HGLRC ghRC;
//HDC ghDC;

// Foward declarations of functions included in this code module:
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

void KoswinDraw();



/*
GLvoid SetupTex(GLvoid)
{
   	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
//	BuildRGBATex(IDB_BITMAP9,IDB_BITMAP10,Shadow);
//	BuildRGBTex(IDB_ECHO,tex_echo);
//	loadjpg("rd\\echo.jpg", 512, &tex_echo);

	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
*/


void KoswinResize(WORD width, WORD height)
{
//	GLfloat aspect;

    glViewport(0, 0, width, height);

/*    aspect = (GLfloat)width/(GLfloat)height;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	gluPerspective(45.0, aspect, 4.0, 10000);
    glMatrixMode(GL_MODELVIEW);
	*/
}

void KoswinInitSystem() {
	KoswinOldTime=timeGetTime();
//	load_agm("rd\\echo.agm",&mod_echo);
}

void KoswinKillSystem(HWND hWnd,HGLRC hRC)
{
	wglMakeCurrent(NULL, NULL);
	ReleaseDC(hWnd,hDC);
	wglDeleteContext(hRC);
	DestroyWindow(hWnd);
	if (hPalette)
	DeleteObject(hPalette);
//	free_agm(&mod_echo);
}

GLvoid KoswinInitializeGL(GLsizei width, GLsizei height)
{
    GLfloat aspect;

   	glClearColor(0.0f,0.0f,0.0f,1.0f);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);

    glEnable(GL_DEPTH_TEST);
 
//	SetupTex();
//	glEnable(GL_LIGHTING);

    glMatrixMode(GL_PROJECTION);
    aspect = (GLfloat)width/(GLfloat)height;
	gluPerspective(45.0, aspect, 1.0, 10000);
    glMatrixMode(GL_MODELVIEW);
	GLfloat ambient[]= {0.2f,0.2f,0.2f,1.0f};
	GLfloat specular[]= {1.0f,1.0f,1.0f,1.0f};
	GLfloat diffuse[]= {0.6f,0.6f,0.6f,1.0f};
	GLfloat lightpos2[]= {2.0f,200.0f,1.0f,1.0f};

	glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,180);//Angle);
	glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
	glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
	glLightfv(GL_LIGHT0,GL_POSITION,lightpos2);
//	glEnable(GL_LIGHT0);

	glShadeModel(GL_SMOOTH);

	glEnable(GL_COLOR_MATERIAL);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER,0.01f);
 
	GLfloat FogColor[]= {0.6f,0.6f,0.6f,1.0f};

//	glEnable(GL_FOG);
	glFogf(GL_FOG_START ,100.0f);
	glFogf(GL_FOG_END ,200.0f);
	glFogf(GL_FOG_DENSITY ,0.5f);
	glFogfv(GL_FOG_COLOR, FogColor);
}

HWND
CreateOpenGLWindow(wchar_t* title, int x, int y, int width, int height, 
		   BYTE type, DWORD flags)
{
    int         n, pf;
    HWND        hWnd;
    WNDCLASS    wc;
    LOGPALETTE* lpPal;
    PIXELFORMATDESCRIPTOR pfd;
    static HINSTANCE hInstance = 0;

    /* only register the window class once - use hInstance as a flag. */
    if (!hInstance) {
	hInstance = GetModuleHandle(NULL);
	wc.style         = CS_OWNDC;
	wc.lpfnWndProc   = (WNDPROC)WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = NULL;
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = L"Koswin";

	if (!RegisterClass(&wc)) {
	    MessageBox(NULL, L"RegisterClass() failed:  "
		       L"Cannot register window class.", L"Error", MB_OK);
	    return NULL;
	}
    }

    hWnd = CreateWindow(L"Koswin", title, WS_OVERLAPPEDWINDOW | 
			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZE,
			x, y, width, height, NULL, NULL, hInstance, NULL);

    if (hWnd == NULL) 
	{
		MessageBox(NULL, L"CreateWindow() failed:  Cannot create a window.",L"Error", MB_OK);
		return NULL;
    }

    hDC = GetDC(hWnd);

    /* there is no guarantee that the contents of the stack that become
       the pfd are zeroed, therefore _make sure_ to clear these bits. */
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize        = sizeof(pfd);
    pfd.nVersion     = 1;
    pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags;
    pfd.iPixelType   = type;
    pfd.cColorBits   = 32;

    pf = ChoosePixelFormat(hDC, &pfd);
    if (pf == 0) 
	{
		MessageBox(NULL, L"ChoosePixelFormat() failed:  "
		   L"Cannot find a suitable pixel format.", L"Error", MB_OK); 
		return 0;
    } 
 
    if (SetPixelFormat(hDC, pf, &pfd) == FALSE) 
	{
		MessageBox(NULL, L"SetPixelFormat() failed:  "
		   L"Cannot set format specified.", L"Error", MB_OK);
		return 0;
    } 

    DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

    if (pfd.dwFlags & PFD_NEED_PALETTE ||
	pfd.iPixelType == PFD_TYPE_COLORINDEX) {

	n = 1 << pfd.cColorBits;
	if (n > 256) n = 256;

	lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
				    sizeof(PALETTEENTRY) * n);
	memset(lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
	lpPal->palVersion = 0x300;
	lpPal->palNumEntries = n;

	GetSystemPaletteEntries(hDC, 0, n, &lpPal->palPalEntry[0]);
    
	/* if the pixel type is RGBA, then we want to make an RGB ramp,
	   otherwise (color index) set individual colors. */
	if (pfd.iPixelType == PFD_TYPE_RGBA) {
	    int redMask = (1 << pfd.cRedBits) - 1;
	    int greenMask = (1 << pfd.cGreenBits) - 1;
	    int blueMask = (1 << pfd.cBlueBits) - 1;
	    int i;

	    /* fill in the entries with an RGB color ramp. */
	    for (i = 0; i < n; ++i) {
		lpPal->palPalEntry[i].peRed = 
		    (((i >> pfd.cRedShift)   & redMask)   * 255) / redMask;
		lpPal->palPalEntry[i].peGreen = 
		    (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
		lpPal->palPalEntry[i].peBlue = 
		    (((i >> pfd.cBlueShift)  & blueMask)  * 255) / blueMask;
		lpPal->palPalEntry[i].peFlags = 0;
	    }
	} else {
	    lpPal->palPalEntry[0].peRed = 0;
	    lpPal->palPalEntry[0].peGreen = 0;
	    lpPal->palPalEntry[0].peBlue = 0;
	    lpPal->palPalEntry[0].peFlags = PC_NOCOLLAPSE;
	    lpPal->palPalEntry[1].peRed = 255;
	    lpPal->palPalEntry[1].peGreen = 0;
	    lpPal->palPalEntry[1].peBlue = 0;
	    lpPal->palPalEntry[1].peFlags = PC_NOCOLLAPSE;
	    lpPal->palPalEntry[2].peRed = 0;
	    lpPal->palPalEntry[2].peGreen = 255;
	    lpPal->palPalEntry[2].peBlue = 0;
	    lpPal->palPalEntry[2].peFlags = PC_NOCOLLAPSE;
	    lpPal->palPalEntry[3].peRed = 0;
	    lpPal->palPalEntry[3].peGreen = 0;
	    lpPal->palPalEntry[3].peBlue = 255;
	    lpPal->palPalEntry[3].peFlags = PC_NOCOLLAPSE;
	}

	hPalette = CreatePalette(lpPal);
	if (hPalette) {
	    SelectPalette(hDC, hPalette, FALSE);
	    RealizePalette(hDC);
	}

	free(lpPal);
    }

    ReleaseDC(hWnd,hDC);

    return hWnd;
}   


int APIENTRY
WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
	LPSTR lpszCmdLine, int nCmdShow)
{
    HGLRC hRC;				/* opengl context */
    DWORD buffer = PFD_DOUBLEBUFFER;	/* buffering type */
    BYTE  color  = PFD_TYPE_RGBA;	/* color type */
	RECT rect;
 
    if (strstr(lpszCmdLine, "-sb")) 
	{
		buffer = 0;
    } 
    if (strstr(lpszCmdLine, "-ci")) 
	{
		color = PFD_TYPE_COLORINDEX;
    } 
    if (strstr(lpszCmdLine, "-h")) 
	{
		MessageBox(NULL, L"animate [-ci] [-sb]\n"
			L"  -sb   single buffered\n"
			L"  -ci   color index\n",
			L"Usage help", MB_ICONINFORMATION);
		exit(0);
    }

	GetClientRect(GetDesktopWindow(),&rect);

    hWnd = CreateOpenGLWindow(L"Echo", 0, 0, rect.right, rect.bottom, color, buffer);

	if (hWnd == NULL)
		exit(1);
	
    hDC = GetDC(hWnd);
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

	KoswinInitSystem();
	GetClientRect(hWnd,&rect);
	KoswinInitializeGL(rect.right, rect.bottom);
	JoyInput.Create(hCurrentInst,hWnd);

    ShowWindow(hWnd, SW_MAXIMIZE);
    UpdateWindow(hWnd);

	SystemUpdate();
	GameLoop();
 
	JoyInput.Destroy();
   	KoswinKillSystem(hWnd,hRC);

    return 0;
}

int SystemUpdate() {
	MSG   msg;				/* message */
	do { 
		while(!m_Quitting && PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) {
			if(GetMessage(&msg, hWnd, 0, 0)) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			} else {
				return 1;
			}
		}
	} while (m_Active==false && !m_Quitting);
	return m_Quitting?1:0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
//	HDC hdc;
//	TCHAR szHello[MAX_LOADSTRING];
//	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			//switch (wmId)
			//{
			//	case IDM_EXIT:
			//	   DestroyWindow(hWnd);
			//	   m_Quitting = true;
			//	   break;
			//	default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			//}
			break;
		case WM_PAINT:
//			KoswinDraw();
			BeginPaint(hWnd, &ps);
			EndPaint(hWnd, &ps);
			break;
		case WM_ERASEBKGND:
			return 0;
			break;
		case WM_SIZE:
			KoswinResize(LOWORD(lParam),HIWORD(lParam)); 
			PostMessage(hWnd, WM_PAINT, 0, 0);
			break;
		case WM_SETFOCUS:
			m_Active=true;
			break;
		case WM_KILLFOCUS:
			m_Active=false;
			break;
		case WM_CHAR:
			switch (wParam) {
			case 27:			/* ESC key */
				PostQuitMessage(0);
				break;
			}
			return 0;
			break;	
			
		case WM_PALETTECHANGED:
			if (hWnd == (HWND)wParam)
			break;
			/* fall through to WM_QUERYNEWPALETTE */
		case WM_QUERYNEWPALETTE:
			if (hPalette) {
				UnrealizeObject(hPalette);
				SelectPalette(hDC, hPalette, FALSE);
				RealizePalette(hDC);
				return TRUE;
			}
			return FALSE;
		case WM_CLOSE:
		case WM_DESTROY:
			PostQuitMessage(0);
			m_Quitting = true;
			break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}







 

